package com.hyts.sdkhttp.domain;

import com.hyts.sdkhttp.constant.ConnectionConfigure;
import com.hyts.sdkhttp.error.SdkConnectionError;
import com.hyts.sdkhttp.util.StringUtil;
import com.hyts.sdkhttp.util.UploadUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

/**
 * project-name:iscloud package-name:com.ultrapower.zq.handler author:Libo/Alex
 * create-date:2018-03-12 10:27 copyright:libo-hyts-github
 * email:libo2dev@aliyun.com description:此类主要用于:
 * 封装原生HttpURLConnection/URLConnection对象进行Http传输信息
 */
public final class SdkURLConnection {

	/**
	 * 内置封装java原生态url Connection对象连接：需要在后期对此对象封装为connection对象
	 */
	private HttpURLConnection connection;

	/**
	 * 请求服务类对象
	 */
	private static SdkRequest request;

	/*******************
	 * 以下属性仅限于post或者非get请求时设置*********start
	 ************************/
	/**
	 * 是否输出
	 */
	boolean isDoOuput = true;

	/**
	 * 是否输入
	 */
	boolean isDoInput = true;

	/**
	 * 是否用开始
	 */
	boolean isUseCache = false;

	/*******************
	 * 以下属性仅限于post或者非get请求时设置*********end
	 ************************/
	/**
	 * 连接时间超时设置 10000 毫秒
	 */
	int connectionTimeout = Integer.valueOf(ConnectionConfigure.CONNECT_TIMEOUT.getValue().toString());

	/**
	 * 读取时间超时设置 2000 毫秒
	 */
	int readTimeout = Integer.valueOf(ConnectionConfigure.READ_TIMEOUT.getValue().toString());

	/**
	 * 创建一个新的实例-构造器 SdkURLConnection.
	 * 
	 * @throws SdkConnectionError
	 * @throws IOException
	 * @throws MalformedURLException
	 */
	public SdkURLConnection() throws MalformedURLException, SdkConnectionError, IOException {
	}

	/**
	 * 创建一个新的实例-构造器 SdkURLConnection.
	 * 
	 * @throws SdkConnectionError
	 * @throws IOException
	 * @throws MalformedURLException
	 */
	public SdkURLConnection(SdkRequest request) throws SdkConnectionError, MalformedURLException, IOException {
		// 执行构建操作
		build(request);
	}

	// 构建读取超时时间
	public SdkURLConnection buildReadTimeout(int readTimeout) {
		this.readTimeout = readTimeout;
		return this;
	}

	// 构建连接超时时间
	public SdkURLConnection buildConnectionTimeout(int connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
		return this;
	}

	// 构建输出
	public SdkURLConnection buildDoOutput(int connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
		return this;
	}

	// 构建输入
	public SdkURLConnection buildDoInput(int connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
		return this;
	}

	// 构建请求对象
	/*
	 * public SdkURLConnection buildRequest(SdkRequest request) { request = request;
	 * return this; }
	 */
	// 构建操作
	public SdkURLConnection build(SdkRequest request) throws SdkConnectionError, MalformedURLException, IOException {
		// 校验路径或者对象是否为空!
		if (Objects.isNull(request) || StringUtil.isEmpty(request.getUrl())) {
			throw new SdkConnectionError("无法构造出SdkRequest对象为空的SdkURLConnection对象,请设置SdkRequest对象！");
		}
		// 连接超时时间
		connection = (HttpURLConnection) new URL(request.getUrl()).openConnection();
		// 设置基础参数配置
		connection.setConnectTimeout(connectionTimeout);// 不设置则默认连接超时时
		connection.setReadTimeout(readTimeout);// 不设置则默认读取信息时间
		connection.setRequestMethod(request.getRequestMethod().getValue());
		// 设置header请求参数属性
		connection.setRequestProperty("Charset", request.getCharset().getValue());
		connection.setRequestProperty("Content-Type", request.getContentType().getValue());
		connection.setRequestProperty("accept", "*/*");
		if (request.isConnectionKeepAlive())
			connection.setRequestProperty("Connection", "Keep-Alive");// 维持长连接
		// 选择合适的Http请求方法进行构造其他参数
		switch (request.getRequestMethod()) {
		case GET:
			connection.setDoOutput(!isDoOuput);// 禁止 URL 连接进行输出，默认为“false”
			connection.setDoInput(isDoInput);// 使用 URL 连接进行输入，默认为“true”
			connection.setUseCaches(isUseCache);// 忽略缓存
			break;
		case POST:
			connection.setDoOutput(isDoOuput);// 使用 URL 连接进行输出，默认为“false”
			connection.setDoInput(isDoInput);// 使用 URL 连接进行输入，默认为“true”
			connection.setUseCaches(isUseCache);// 忽略缓存
			break;
		case PUT:
			// 暂时不进行任何操作：之后等待完善
			// TODO
			throw new UnsupportedOperationException("不支持PUT请求操作");
		case DELETE:
			// 暂时不进行任何操作：之后等待完善
			// TODO
			throw new UnsupportedOperationException("不支持PUT请求操作");
		case HEAD:
			// 暂时不进行任何操作：之后等待完善
			// TODO
			throw new UnsupportedOperationException("不支持PUT请求操作");
		}
		// 判断是否属于传入请求提参数
		if (Objects.nonNull(request)) {
			// 调用启动初始化状态操作
			try {
				switch (request.getContentType()) {
				case JSON_DATA:
					if (Objects.nonNull(request.getParams())) {
						OutputStream outwritestream = connection.getOutputStream();
						outwritestream.write(request.getParams().toJSONString().getBytes());
						outwritestream.flush();
						outwritestream.close();
					}
					break;
				case MULTIPART_DATA:
					OutputStream outwritestream = connection.getOutputStream();
					SdkUploadRequest request2 = (SdkUploadRequest) request;
					String fileName = request2.getFileName();
					DataOutputStream dos = new DataOutputStream(outwritestream);
					try (InputStream is = new FileInputStream(new File(request2.getFilePath()));) {
						// 校验循环参数列表
						if (Objects.nonNull(request2.getParams())) {
							Set<Entry<String, Object>> kv = request2.getParams().entrySet();
							kv.forEach(param -> {
								try {
									dos.writeBytes((UploadUtils.buildStart() + UploadUtils.TOKEN_03));
									dos.writeBytes(UploadUtils.buildContentDispositionParam(param.getKey()));
									dos.writeBytes(UploadUtils.TOKEN_03);
									dos.writeBytes(param.getValue().toString());
									dos.writeBytes(UploadUtils.TOKEN_03);
								} catch (IOException e) {
									e.printStackTrace();
								}
							});
						}
						// 校验循环文件列表
						dos.writeBytes((UploadUtils.buildStart()));
						dos.writeBytes((UploadUtils.buildContentDispositionFile(request2.getFileKeyName(), fileName)));
						dos.writeBytes(UploadUtils.TOKEN_03);
						dos.writeBytes("Content-Type: application/octet-stream"+UploadUtils.TOKEN_03);
						dos.writeBytes(UploadUtils.TOKEN_03);
						int length = 0;
						byte[] temp = new byte[1024];
						while ((length = is.read(temp)) > -1) {
							dos.write(temp, 0, length);
						}
						dos.writeBytes(UploadUtils.TOKEN_03);
						is.close();
						dos.writeBytes(UploadUtils.buildStart());
						outwritestream.flush();
						outwritestream.close();
						break;
					} catch (Exception e) {
						e.printStackTrace();
					}
				case FORM_URLENCODE_DATA:
					break;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return this;
	}

	/**  
	 * @Title: build  
	 * @Description: 构建操作  
	 * @param  无   
	 * @return SdkURLConnection    返回类型  
	 * @throws  MalformedURLException,IOException,SdkConnectionError
	 */ 
	public SdkURLConnection build() throws SdkConnectionError, MalformedURLException, IOException {
		return this.build(request);
	}

	// 获取连接对象
	public HttpURLConnection getConnection() {
		return this.connection;
	}
}
